from compiler.ast import *
import compiler
import sys

global varlevel
varlevel = 1
global filelines1
filelines1=[]
global filelines
global filename
filename=[]
filelines=[]
global var
var=0
global listvar
listvar=[]

def flaten(n):
 global var
 global listvar
 if isinstance(n, Module):
  flaten(n.node)
  return var
 elif isinstance(n, Stmt):
  [flaten(x) for x in n.nodes]
  return 1 
 elif isinstance(n, Printnl):
  line =  "print " + flaten(n.nodes[0])
  filelines.append(line)
  filelines.append("\n")
  return 1 
 elif isinstance(n, Assign):
  temp =(flaten(n.nodes[0]))
  listvar.append(temp)
  line = temp + '=' +str(flaten(n.expr))
  filelines.append(line)
  filelines.append("\n")
  return 1
 elif isinstance(n, AssName):
  return n.name
 elif isinstance(n, Discard):
  flaten(n.expr)
  return ''
 elif isinstance(n, Const):
  s  = n.value
  return str(s)
 elif isinstance(n, Name):
  return n.name
 elif isinstance(n, Add):  
  nhvar1 =flaten(n.left)
  nhvar2 =flaten(n.right)
  nhvar3 = "nh"+str(var)
  var += 1
  line =  nhvar3+" = "+nhvar1+" + "+nhvar2
  listvar.append(nhvar3)
  filelines.append(line)
  filelines.append("\n")
  return nhvar3
 elif isinstance(n, UnarySub):
  nhvar4 = flaten(n.expr)
  nhvar5 = "nh"+str(var)
  line = nhvar5 +"= -"+nhvar4
  var+=1
  listvar.append(nhvar5)
  filelines.append(line)
  filelines.append("\n")
  return nhvar5
 elif isinstance(n, CallFunc):
  nhvar2 = "nh"+str(var)
  line = nhvar2 +" = input()" 
  var += 1
  listvar.append(nhvar2)
  filelines.append(line)
  filelines.append("\n")
  return nhvar2
 else:
  raise Exception('Error in flaten: unrecognized AST node')
   
def convertx86(n):
 global varlevel
 global var
 global listvar 
 global num
 if isinstance(n, Module):
  convertx86(n.node)
  return 1
 elif isinstance(n, Stmt):
  return 1 + sum([convertx86(x) for x in n.nodes])
 elif isinstance(n, Printnl):
  temp = convertx86(n.nodes[0])
  if isinstance(temp,str):
   numtemp = listvar.index(temp)
   numtemp = (numtemp+1)*4
   insval = str(numtemp)
   line = "	pushl -"+insval+"(%ebp)\n"
   filelines1.append(line)
   line = "	call print_int_nl\n"
   filelines1.append(line)
   line = "	addl $4, %esp\n"
   filelines1.append(line)
   filelines1.append("\n")
  else:
   line = "	pushl $" + str(temp)
   filelines1.append(line)
   filelines1.append("\n")
   line = "	call print_int_nl\n"
   filelines1.append(line)
   line = "	addl $4, %esp\n"
   filelines1.append(line)
   filelines1.append("\n")
  return 1
 elif isinstance(n, Assign):
  temp = convertx86(n.nodes[0])
  num = listvar.index(temp)
  tempassign = convertx86(n.expr)
  if isinstance(tempassign,str):
   numtemp = listvar.index(tempassign)
   numtemp = (numtemp +1)*4
   insval = str(numtemp)
   line = "	movl -"+insval+"(%ebp), %eax\n"
   filelines1.append(line)
   num1 = (num+1)*4  
   insval = str(num1)
   line = "	movl %eax, -"+insval+"(%ebp)\n" 	
   filelines1.append(line)
   filelines1.append("\n")
  elif isinstance(tempassign,int):
   num1 = (num+1)*4
   insval = str(num1)
   line = "	movl $"+str(tempassign)+", -"+insval+"(%ebp)\n"
   filelines1.append(line)
   filelines1.append("\n")
  return 1

 elif isinstance(n, AssName):
  return n.name
 elif isinstance(n, Discard):
  return 1 + convertx86(n.expr)
 elif isinstance(n, Const):
  return n.value
 elif isinstance(n, Name):
  return n.name
 elif isinstance(n, Add):
  temp1 = convertx86(n.left)
  temp2 = convertx86(n.right)
  if isinstance(temp1,int):
   if isinstance(temp2, int):
    line = "	movl $"+str(temp1)+", %eax\n"
    filelines1.append(line)
    filelines1.append("\n")
    line = "	addl $"+str(temp2)+", %eax\n"
    filelines1.append(line)
    num1 = (num+1)*4  
    insval = str(num1)
    line = "	movl %eax, -"+insval+"(%ebp)\n"
    filelines1.append(line)
    filelines1.append("\n")
   elif isinstance(temp2, str):
    numtemp = listvar.index(temp2)
    numtemp  = (numtemp+1)*4
    insval = str(numtemp)
    line = "	movl -"+insval+"(%ebp), %eax\n" 
    filelines1.append(line)
    num1 = (num+1)*4  
    insval = str(num1)
    line = "	movl %eax, -"+insval+"(%ebp)\n"
    filelines1.append(line)
    line = "	addl $"+str(temp1)+", -"+insval+"(%ebp)\n"
    filelines1.append(line)
    filelines1.append("\n")
  elif isinstance(temp1,str):
   if isinstance(temp2,int):
    numtemp = listvar.index(temp1)
    numtemp = (numtemp+1)*4
    insval = str(numtemp)
    line = "	movl -"+insval+"(%ebp), %eax\n"
    filelines1.append(line)
    num1 = (num+1)*4  
    insval = str(num1)
    line = "	movl %eax, -"+insval+"(%ebp)\n"
    filelines1.append(line)
    line = "	addl $"+str(temp2)+", -"+insval+"(%ebp)\n"
    filelines1.append(line)
    filelines1.append("\n")
   elif isinstance(temp2,str):
    numtemp = listvar.index(temp1)
    numtemp = (numtemp+1)*4
    insval = str(numtemp)
    line = "	movl -" +insval+"(%ebp),%eax\n"
    filelines1.append(line)
    numtemp = listvar.index(temp2)
    numtemp = (numtemp+1)*4
    insval = str(numtemp)
    line = "	addl -"+insval+"(%ebp), %eax\n"
    filelines1.append(line)
    num1 = (num+1)*4  
    insval = str(num1)
    line  = "	movl %eax, -" + insval + "(%ebp)\n"
    filelines1.append(line)
    filelines1.append("\n")   	
  pass

 elif isinstance(n, UnarySub):
  negval = convertx86(n.expr)
  if isinstance(negval,int):
   num1 = (num+1)*4  
   insval = str(num1)
   line = "	movl $"+str(negval)+", %eax\n"
   filelines1.append(line)
   line = "	movl %eax, -"+insval+"(%ebp)\n"
   filelines1.append(line)
   line = "	negl -"+insval+"(%ebp)\n"
   filelines1.append(line)
   filelines1.append("\n")
  elif isinstance(negval,str):
   numtemp = listvar.index(negval)
   numtemp = (numtemp+1)*4
   insval = str(numtemp)
   line = "	movl -"+insval+"(%ebp), %eax\n"
   filelines1.append(line)
   num1 = (num+1)*4  
   insval = str(num1)
   line = "	movl %eax, -"+insval+"(%ebp)\n"
   filelines1.append(line)
   line = "	negl -"+insval+"(%ebp)\n"
   filelines1.append(line)
   filelines1.append("\n")
  pass

 elif isinstance(n, CallFunc):
  line = "	call input\n"
  filelines1.append(line)
  num1 = (num+1)*4  
  insval = str(num1)
  line = "	movl %eax, -"+insval+"(%ebp)\n"
  filelines1.append(line)
  filelines1.append("\n")
  pass
 else:
  raise Exception("Error in convert: unrecognized AST node")

def main():
 flatast = compiler.parseFile("inter.py")
 filelines1start =[]
 filelines1end = []
 filelines1start.append(".globl main")
 filelines1start.append("\n")
 filelines1start.append("main:\n")
 filelines1start.append("\n")
 var = len(listvar)
 varalloc = var*4
 varstr = str(varalloc)
 filelines1start.append("	pushl %ebp\n")
 filelines1start.append("	movl %esp, %ebp\n")
 varalloc = var*4
 varstr = str(varalloc)
 line = "	subl $"+varstr+",%esp"
 filelines1start.append(line)
 filelines1start.append("\n")
 filelines1start.append("\n")
 filelines1end.append("	movl $0, %eax")
 filelines1end.append("\n")
 filelines1end.append("	leave")
 filelines1end.append("\n")
 filelines1end.append("	ret")
 filelines1end.append("\n")
 temp =sys.argv[1]
 l = len(temp)
 temp = temp[:l-3]
 FILE = open(temp+".s","w")
 a = convertx86(flatast)
 FILE.writelines(filelines1start)
 FILE.writelines(filelines1)
 FILE.writelines(filelines1end)
 FILE.close()  

def P0_Compiler():
 ast = compiler.parseFile(sys.argv[1])
 filelinesstart =[]
 a= flaten(ast)
 filelinesstart.append("#!/usr/bin/python")
 filelinesstart.append("\n")
 FILE = open("inter.py","w")
 FILE.writelines(filelinesstart)
 FILE.writelines(filelines)
 FILE.close()
 main()
 
P0_Compiler()



